package com.xinjian.jianba.task;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import com.xinjian.jianba.config.RedissonManager;
import com.xinjian.jianba.dto.BuziVisitCountDto;
import com.xinjian.jianba.service.BuziVisitService;
import com.xinjian.jianba.service.ProcedureService;
import com.xinjian.jianba.service.RedisService;
import com.xinjian.jianba.utils.Constants;

@Configuration
@EnableScheduling
// 启用定时任务
public class Task {
	private static final Logger LOGGER = LoggerFactory.getLogger(Task.class);
	private static final String PROCEDURETASK_REDIS_LOCK="PROCEDURETASK_REDIS_LOCK";
	private static final String BUZI_VISITS_LOCK="BUZI_VISITS_LOCK";
	private static final String H5_ACTI_VOTE_LOCK="H5_ACTI_VOTE_LOCK";
	private static final String PAY_ORDER_LOCK="PAY_ORDER_LOCK";
	@Autowired
	private ProcedureService procedureService;

	@Autowired
	private RedissonManager redissonManager;
	@Autowired
	private RedisService redisService;
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
	@Autowired
	private BuziVisitService buziVisitService;
	
	@Value("${spring.near.geo.db}")
	private String geoDb;

	@Value("${spring.meet.geo.male.db}")
	private String maleGeoDb;

	@Value("${spring.meet.geo.female.db}")
	private String femaleGeoDb;

	@Value("${spring.meet.geo.db}")
	private String meetDb;

	@Value("${spring.meet.geo.male.db}")
	private String maleMeetdb;

	@Value("${spring.meet.geo.female.db}")
	private String femaleMeetdb;

	@Value("${spring.meet.label.db}")
	private String labelDb;

	@Value("${order.period}")
	private Integer orderPeriod;

	// 每隔10分钟运行一次
	@Scheduled(cron = "${jianba.geo.task}")
	public void run() {
        RLock lock = redissonManager.getRedisson().getLock(PROCEDURETASK_REDIS_LOCK);
        boolean getLock = false;
        try {
            if(getLock = lock.tryLock(0,5, TimeUnit.SECONDS)){
            	LOGGER.info("Redisson获取到分布式锁:{},ThreadName:{}",PROCEDURETASK_REDIS_LOCK,Thread.currentThread().getName());
            	//获取到锁,执行任务
            	try {
        			LOGGER.info("-----task----start---------");
        			procedureService.calMeetMatch();
        			procedureService.delMeetData();
        			LOGGER.info("-----task----end---------");
        		} catch (Exception e) {
        			e.printStackTrace();
        		}
            }else{
            	LOGGER.info("Redisson没有获取到分布式锁:{},ThreadName:{}",PROCEDURETASK_REDIS_LOCK,Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
        	LOGGER.error("Redisson分布式锁获取异常",e);
        } finally {
            if(!getLock){
                return;
            }
            lock.unlock();
            LOGGER.info("Redisson分布式锁释放锁");
        }

		
	}

	// 每天凌晨4点清空缓存信息
	//	@Scheduled(cron = "${jianba.clear.redis.cache}")
	public void clearCache() {

		try {
			LOGGER.info("-----task----clearCache---------");
			redisService.del(geoDb);
			redisService.del(maleGeoDb);
			redisService.del(femaleGeoDb);

			redisService.del(meetDb);
			redisService.del(maleMeetdb);
			redisService.del(femaleMeetdb);

			redisService.del(labelDb);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//每天凌晨一点同步昨天数据到数据库,并清除昨天数据
	@Scheduled(cron="${jianba.clear.redis.buzivisit}")
	public void clearBuziVisit(){
		
		LOGGER.info("-----task----clearBuziVisit---------");

        RLock lock = redissonManager.getRedisson().getLock(BUZI_VISITS_LOCK);
        boolean getLock = false;
        try {
            if(getLock = lock.tryLock(0,5, TimeUnit.SECONDS)){
            	LOGGER.info("Redisson获取到分布式锁:{},ThreadName:{}",BUZI_VISITS_LOCK,Thread.currentThread().getName());
            	//获取到锁,执行任务
            	try {
        			LOGGER.info("-----task----clearBuziVisit--start---------");
        			Date dNow = new Date();
        			Calendar calendar = Calendar.getInstance(); 
        			calendar.setTime(dNow);//把当前时间赋给日历
        		    calendar.add(Calendar.DAY_OF_MONTH, -1);  //设置为前一天
        		    Date dBefore = calendar.getTime();   //得到前一天的时间
        		    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); 
        		    String dBeforeStr = sdf.format(dBefore);
        			String preKey=Constants.BUZI_VISIT+dBeforeStr;
        			Set<String> keys=stringRedisTemplate.keys(preKey+"*");
        			BuziVisitCountDto buziVisitCountDto=new BuziVisitCountDto();
        			keys.stream().forEach(key ->{
        				buziVisitCountDto.setBuziId(Long.parseLong(key.substring(key.lastIndexOf("_")+1)));
        				buziVisitCountDto.setCount(stringRedisTemplate.opsForValue().get(key));
        				buziVisitCountDto.setDate(dBeforeStr);
        				try {
        					buziVisitService.insertBuziVisitCount(buziVisitCountDto);
        					LOGGER.info("-----task----clearBuziVisit--end---------");
        				} catch (Exception e) {
        					LOGGER.error("-----task----clearBuziVisit---------{}",e.getMessage());
        				}
        			});
        			stringRedisTemplate.delete(keys);
        		} catch (Exception e) {
        			e.printStackTrace();
        		}
            }else{
            	LOGGER.info("Redisson没有获取到分布式锁:{},ThreadName:{}",BUZI_VISITS_LOCK,Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
        	LOGGER.error("Redisson分布式锁获取异常",e);
        } finally {
            if(!getLock){
                return;
            }
            lock.unlock();
            LOGGER.info("Redisson分布式锁释放锁");
        }

		
	}
	
	
	//每天凌晨一点同步昨天数据到数据库,并清除昨天数据
		@Scheduled(cron="${jianba.clear.redis.vote}")
		public void clearh5AcVoteVisit(){
			
			LOGGER.info("-----task----clearh5AcVoteVisit---------");

	        RLock lock = redissonManager.getRedisson().getLock(H5_ACTI_VOTE_LOCK);
	        boolean getLock = false;
	        try {
	            if(getLock = lock.tryLock(0,5, TimeUnit.SECONDS)){
	            	LOGGER.info("Redisson获取到分布式锁:{},ThreadName:{}",H5_ACTI_VOTE_LOCK,Thread.currentThread().getName());
	            	//获取到锁,执行任务
	            	try {
	        			LOGGER.info("-----task----clearh5AcVoteVisit--start---------");
	        			String preKey=Constants.H5_ACTI_VOTE;
	        			Set<String> keys=stringRedisTemplate.keys(preKey+"*");
	        			stringRedisTemplate.delete(keys);
	        			LOGGER.info("-----task----clearh5AcVoteVisit--end---------");
	        		} catch (Exception e) {
	        			e.printStackTrace();
	        		}
	            }else{
	            	LOGGER.info("Redisson没有获取到分布式锁:{},ThreadName:{}",H5_ACTI_VOTE_LOCK,Thread.currentThread().getName());
	            }
	        } catch (InterruptedException e) {
	        	LOGGER.error("Redisson分布式锁获取异常",e);
	        } finally {
	            if(!getLock){
	                return;
	            }
	            lock.unlock();
	            LOGGER.info("Redisson分布式锁释放锁");
	        }

			
		}
	

	// 每隔1分钟运行一次,批量修改未支付的过期订单
	@Scheduled(cron = "${order.period.task}")
	public void orderPeriod() {
        RLock lock = redissonManager.getRedisson().getLock(PAY_ORDER_LOCK);
        boolean getLock = false;
        try {
            if(getLock = lock.tryLock(0,5, TimeUnit.SECONDS)){
            	LOGGER.info("Redisson获取到分布式锁:{},ThreadName:{}",PAY_ORDER_LOCK,Thread.currentThread().getName());
            	//获取到锁,执行任务
            	try {
        			LOGGER.info("-----orderPeriod----orderPeriod-------start--");
        			//TODO:更新每个商品的数量
        			int line = procedureService.orderPeriod(orderPeriod);
        			LOGGER.info("-----orderPeriod----orderPeriod-----end---line-----" + line);
        		} catch (Exception e) {
        			e.printStackTrace();
        		}
            }else{
            	LOGGER.info("Redisson没有获取到分布式锁:{},ThreadName:{}",PAY_ORDER_LOCK,Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
        	LOGGER.error("Redisson分布式锁获取异常",e);
        } finally {
            if(!getLock){
                return;
            }
            lock.unlock();
            LOGGER.info("Redisson分布式锁释放锁");
        }
	}
}
